#!/usr/bin/env python
# -*- coding:utf-8 -*-

'''
Question:
    when does Consumer born?
    what does Context contain?

'''

import os, sys, signal
import asyncore, asynchat, socket, threading, time

HOST = "127.0.0.1"
PORT = 54344

def DEBUG(format, *args) : print format % args

will_stop = False

def signal_stop( signo, frame ) :
    global  will_stop
    DEBUG( "SERVER catch #%d signal, would stop.", signo )
    will_stop = True
    return
    # signal_stop

class Consumer(object) :
    '''Echo Consumer'''
    def __init__(self, context=None) :
        self.__context = context

    def feed(self, channel_from, record) :
        DEBUG('COMSUMER echo: %s', record)
        channel_from.push(record + '\n')

class EchoChannel(asynchat.async_chat) :
    def    __init__(self, connect, address) :
        asynchat.async_chat.__init__(self, conn=connect)
        self.__connect = connect
        self.__address = address
        self.__buf_incoming = []
        self.__terminator = '\n'
        self.set_terminator(self.__terminator)

    def    collect_incoming_data(self, data) :
        DEBUG('SERVER collect: >>>%s<<<', data)
        self.__buf_incoming.append(data)

    def    found_terminator(self) :
        DEBUG('SERVER found: >>>%s<<<', self.__buf_incoming)
        line = ''.join(self.__buf_incoming)
        self.__buf_incoming = []

        # when should consumer born
        consumer = Consumer()
        consumer.feed(self, line)
        # found_terminator()

    def    handle_close(self) :
        DEBUG('SERVER close connection for client "%s".', self.__address)
        self.close()
        # handle_close()

    # class EchoChannel

class EchoServer(asyncore.dispatcher):

    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.bind(("", port))
        self.listen(5)
        DEBUG('SERVER listening on PORT:%d ...', port)

    def handle_accept(self) :
        connect, client = self.accept()
        DEBUG('SERVER accept client %s', client)

        EchoChannel(connect, client)
        # handle_accept()

    # class EchoServer

def main():
    # mask signal
    DEBUG('os.name: %s', os.name)
    signal.signal( signal.SIGTERM, signal_stop )
    if 'posix' == os.name :
        signal.signal( signal.SIGQUIT, signal_stop )

    s = EchoServer(PORT)
    try :
        asyncore.loop()
    except :
        DEBUG( "SERVER interrupt : %s", `sys.exc_info()[1]` )

if __name__ == '__main__' :
    main()
    sys.exit(0)
